﻿using GamFi.Admin.API.Application.Contracts.User.GetUsers;
using GamFi.Admin.API.Application.Exceptions;
using GamFi.Admin.API.Application.Interfaces;
using GamFi.Admin.API.Application.Resources;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;

namespace GamFi.Admin.API.Application.Features.Queries.User.GetUsers;

/// <summary>
/// Обработчик запроса для получения списка пользователей без общего количества.
/// </summary>
public class GetUsersQueryHandler : IRequestHandler<GetUsersQuery, GetUsersResponse>
{
    private readonly IDbContext _dbContext;
    private readonly IStringLocalizer<ExceptionMessages> _localizer;

    /// <summary>
    /// Конструктор обработчика запроса для получения списка пользователей.
    /// </summary>
    /// <param name="dbContext">Контекст базы данных.</param>
    /// <param name="localizer"></param>
    public GetUsersQueryHandler(IDbContext dbContext, IStringLocalizer<ExceptionMessages> localizer)
    {
        _dbContext = dbContext;
        _localizer = localizer;
    }

    /// <summary>
    /// Обработка запроса для получения списка пользователей.
    /// </summary>
    /// <param name="request">Запрос на получение списка пользователей.</param>
    /// <param name="cancellationToken">Токен для отмены операции.</param>
    /// <returns>Ответ с списком пользователей.</returns>
    public async Task<GetUsersResponse> Handle(GetUsersQuery request, CancellationToken cancellationToken)
    {
        if (request is null)
            throw new RequestException(_localizer[nameof(RequestException.RequestIsEmpty)]);

        // Получение всех пользователей из базы данных
        IQueryable<Domain.Entities.User> query = _dbContext.Users.Include(u => u.UserInfo).ThenInclude(u => u.Country);

        // Применение фильтра, если он предоставлен
        if (!string.IsNullOrEmpty(request.Filter))
        {
            query = query.Where(user =>
                user.UserInfo.FirstName.Contains(request.Filter) ||
                user.UserInfo.LastName.Contains(request.Filter) ||
                user.UserName.Contains(request.Filter) ||
                user.Id.ToString().Contains(request.Filter) ||
                user.WalletId.ToString().Contains(request.Filter) ||
                user.Email.Contains(request.Filter) ||
                user.UserInfoId.ToString().Contains(request.Filter) ||
                user.UserInfo.Patronymic.Contains(request.Filter) ||
                user.UserInfo.CountryId.ToString().Contains(request.Filter) ||
                user.UserInfo.Country.Name.Contains(request.Filter)); // Пример: можно включить фильтрацию по другим полям, если это необходимо
        }

        // Применение пагинации
        var users = await query
            .Skip(request.PageNumber * request.PageSize)
            .Take(request.PageSize)
            .ToListAsync(cancellationToken);

        // Маппинг пользователей в GetUsersResponse
        var response = new GetUsersResponse
        {
            Users = users.Select(user => new UserDto
            {
                UserInfoId = user.UserInfoId,
                CountryId = user.UserInfo.CountryId,
                FirstName = user.UserInfo.FirstName,
                LastName = user.UserInfo.LastName,
                Patronymic = user.UserInfo.Patronymic,
                UserName = user.UserName ?? "Unknown",
                ImageId = user.UserInfo.ImageId,
                WalletId = user.WalletId
            }).ToList()
        };

        return response;
    }
}